<?php

namespace backend\utils;
use yii\db\Exception;

class GWCurl{
    private $host;
    private $authRandomKey;
    private $authNonce;
    private $authTimestamp;
    private $authAppId;
    private $authVersion;
    private $authStage;
    private $secret;

    /**
     * GWCurl constructor.
     */
    public function __construct()
    {
        // 配置参考应用管理 ->  概况中的值
        $this->host = 'https://open.basic.jxeduyun.com';
        //请求体加密密钥密文，请求体如果需要加密传输则传，明文传输不传。服务器根据此内容获取请求体加密密钥明文。
        $this->authRandomKey = "";
        $this->authNonce = $this->uuid();
        $this->authTimestamp = $this->get_total_millisecond();
        $this->authAppId = "185d55baa58446ee8aca2e6d74131619";
        $this->authVersion  = "1";
        $this->authStage = "RELEASE";
        $this->secret = "3ea1942f563a476f5b07c6b24f11366a";
    }

    /**
     * 发送HTTP请求方法
     * @param  string $url    请求URL
     * @param  array  $params 请求参数
     * @param  string $method 请求方法GET/POST
     * @param  array $header  请求头
     * @param  boolean $multi 是否传文件
     * @return array  $data  响应数据
     * @throws Exception
     */
    function http($url, $params, $method = 'GET', $header = array(), $multi = false){
        $opts = array(
            CURLOPT_TIMEOUT        => 30,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_HTTPHEADER     => $header,
            CURLINFO_HEADER_OUT => true,
            CURLOPT_HEADER => true// 返回 response_header, 该选项非常重要,如果不为 true, 只会获得响应的正文
        );

        /* 根据请求类型设置特定参数 */
        switch(strtoupper($method)){
            case 'GET':
                $opts[CURLOPT_URL] = $url . '?' . http_build_query($params);
                break;
            case 'POST':
                //判断是否传输文件
                $params = $multi ? $params : http_build_query($params);
                $opts[CURLOPT_URL] = $url;
                $opts[CURLOPT_POST] = 1;
                $opts[CURLOPT_POSTFIELDS] = $params;
                break;
            default:
                throw new Exception('不支持的请求方式！');
        }

        /* 初始化并执行curl请求 */
        $ch = curl_init();
        curl_setopt_array($ch, $opts);
        $data  = curl_exec($ch);
        $error = curl_error($ch);

        // 获得响应结果里的：头大小
        $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
        // 根据头大小去获取头信息内容
        $responseHeader = explode("\r\n", substr($data, 0, $headerSize));
        //var_dump($responseHeader);
        $responseBody =json_decode(substr($data, $headerSize), true);
        //var_dump($responseBody);
        $response = array("head"=>$responseHeader,"body"=>$responseBody);

        curl_close($ch);
        if($error) throw new Exception('请求发生错误：' . $error);
        return  $response;
    }
    /**
     * 为签名拼接参数
     */
    function buildStringToSign($headValue = array()){
        $ret = array();
        $num = count($headValue);
        for($i=0;$i<$num;++$i){
            if(!empty($headValue[$i])){
                array_push($ret, $headValue[$i]);
            }
        }
        return implode('|',$ret);
    }
    /**
     * 计算签名
     * @param $router
     * @param $secret
     * @param $authRandomKey
     * @param $authNonce
     * @param $authTimestamp
     * @param $authAppId
     * @param $contentMd5
     * @return string
     */
    function sign($router, $secret, $authRandomKey, $authNonce, $authTimestamp, $authAppId, $contentMd5){
        $values = array();
        $values[0] = $router;
        $values[1] = $authRandomKey;
        $values[2] = $authNonce;
        $values[3] = $authTimestamp;
        $values[4] = $authAppId;
        $values[5] = $contentMd5;
        $stringToSign = $this->buildStringToSign($values);
        $AuthSignature = hash_hmac('sha256', $stringToSign, $secret, true);
        return base64_encode($AuthSignature);
    }

    /**
     * 设置请求头
     * @param string $router
     * @param string $contentMd5
     * @return array
     */
    function setHeader($router,$contentMd5){
        $authRandomKey = $this->authRandomKey;
        $authNonce = $this->authNonce;
        $authTimestamp = $this->authTimestamp;
        $authAppId = $this->authAppId;
        $authStage  = $this->authStage;
        $authVersion  = $this->authVersion;
        $secret = $this->secret;
        $authSignature = $this->sign($router,$secret, $authRandomKey, $authNonce, $authTimestamp, $authAppId, $contentMd5);
        $header = array(
            "Accept: application/json",
            "Content-Type: application/json;charset=utf-8",
            "S-Auth-Stage:".$authStage,
            "S-Auth-AppId:".$authAppId,
            "S-Auth-Timestamp:".$authTimestamp,
            "S-Auth-Nonce:".$authNonce,
            "S-Auth-Signature:".$authSignature
        );
        if(!empty($authRandomKey)){
            array_push($header, "S-Auth-RandomKey:".$authRandomKey);
        }
        if(!empty($authVersion)){
            array_push($header, "S-Auth-Version:".$authVersion);
        }
        if(!empty($contentMd5)){
            array_push($header, "S-Content-MD5:".$contentMd5);
        }
        //var_dump($header);
        return $header;
    }
    /**
     *
     *返回字符串的毫秒数时间戳
     */
    function get_total_millisecond()
    {
        $time = explode (" ", microtime () );
        $time = $time [1] . ($time [0] * 1000);
        $time2 = explode ( ".", $time );
        $time = $time2 [0];
        return $time;
    }
    /**
     * Generates an UUID
     *
     * @author     Anis uddin Ahmad
     * @param      string  an optional prefix
     * @return     string  the formatted uuid
     */
    function uuid($prefix = '')
    {
        $chars = md5(uniqid(mt_rand(), true));
        $uuid  = substr($chars,0,8) . '-';
        $uuid .= substr($chars,8,4) . '-';
        $uuid .= substr($chars,12,4) . '-';
        $uuid .= substr($chars,16,4) . '-';
        $uuid .= substr($chars,20,12);
        return $prefix . $uuid;
    }
    /**
     * http请求get方法
     * @param $router
     * @param $params
     * @param $md5
     * @return array
     * @throws Exception
     */
    public function get($router, $params, $md5){
        $header = $this->setHeader($router,$md5);
        $url = $this->host.$router;
        return $this->http($url, $params, 'GET', $header, false);
    }
    /**
     * http请求post方法
     * @param string $router
     * @param array $params
     * @param boolean $multi 是否传文件
     * @param string $md5
     * @return array
     * @throws Exception
     */
    public function post($router, $params, $multi=false, $md5=null){
        $header = $this->setHeader($router,$md5);
        $url = $this->host.$router;
        return $this->http($url, $params, 'POST', $header, $multi);
    }

    /**
     * @param $router
     * @param $params
     * @param bool $multi
     * @param null $md5
     * @return mixed
     * @throws Exception
     */
    public function postBody($router, $params, $multi=false, $md5=null){
        $res = $this->post($router, $params, $multi, $md5);
        return $res["body"];
    }

    public function postData($router, $params, $multi=false, $md5=null){
        $res = $this->postBody($router, $params, $multi, $md5);
        if($res["statusCode"]) throw new Exception('请求发生异常：'.$res["statusCode"].'=>' . $res["message"]);
        return $res["code"]=='1'?$res["data"]:'';
    }

}